home *** CD-ROM | disk | FTP | other *** search
- /* $Id: plcore.c,v 1.39 1994/08/25 04:06:26 mjl Exp $
- * $Log: plcore.c,v $
- * Revision 1.39 1994/08/25 04:06:26 mjl
- * Moved call of plClrCWindows() to plP_eop where it belongs.
- *
- * Revision 1.38 1994/08/10 05:30:18 mjl
- * Reversed the order of stream destruction when plend() is called -- now the
- * last-created stream gets destroyed first. Makes more sense this way and
- * works more robustly with the x14c demo.
- *
- * Revision 1.37 1994/07/12 19:20:31 mjl
- * Two bugs fixed: cmap1 palette should now "stick" on plots saved from Tk
- * driver, and the code won't complain when a bop isn't preceded by an eop.
- *
- * Revision 1.36 1994/07/08 22:50:31 mjl
- * Fixed bug that was hosing the background color in plots saved from the
- * Tk/DP driver menu.
- *
- * Revision 1.35 1994/07/03 05:50:22 mjl
- * Added fix to prevent an infinite loop while exiting under certain error
- * conditions, submitted by Radey Shouman.
- *
- * Revision 1.34 1994/07/02 21:32:11 mjl
- * Ensure that fflush() is never called with a null pointer, since some
- * systems don't like it (submitted by Neal Holtz).
- *
- * Revision 1.33 1994/06/30 18:26:16 mjl
- * All core source files: made another pass to eliminate warnings when using
- * gcc -Wall. Lots of cleaning up: got rid of includes of math.h or string.h
- * (now included by plplot.h), and other minor changes. Now each file has
- * global access to the plstream pointer via extern; many accessor functions
- * eliminated as a result. Driver interface changed to keep track of current
- * status; plsc->status is set to one of AT_BOP, DRAWING, or AT_EOP. This
- * makes it easy to catch missing plbop/pleop's, and to collapse multiple
- * plbop's or pleop's into a single one. Subpage initialization code moved
- * to plpage.c.
- *
- * Revision 1.32 1994/06/09 20:31:30 mjl
- * Small changes to the way plmkstrm() works.
- *
- * Revision 1.31 1994/05/07 03:23:07 mjl
- * Eliminated some obsolete operations involving fgcolor and bgcolor.
- *
- * Revision 1.30 1994/04/30 16:15:06 mjl
- * Fixed format field (%ld instead of %d) or introduced casts where
- * appropriate to eliminate warnings given by gcc -Wall.
- *
- * Revision 1.29 1994/04/08 12:31:39 mjl
- * Removed driver interface handling of nopause (it was a bad idea). Added
- * call to (*plsc->tidy) [if defined] in plP_tidy. Added a function
- * plsMouseEH for setting the mouse event handler (contributed by Radey
- * Shouman).
- *
- * Revision 1.28 1994/03/23 08:02:48 mjl
- * Provided for handling more basic operations in the driver interface rather
- * than the drivers themselves (pls->nopause, resetting stream parameters
- * after a tidy, etc). Added support for hardware fill -- if the device does
- * not support the operation, the function plfill_soft is used instead.
- * Pattern fill number set/get access functions added.
- *
- * Many debugging remnants from driver interface development removed.
- *
- * Many functions moved elsewhere (this file has gotten too large):
- *
- * plwarn plexit plcol0 plcol1 plrgb plrgb1 plscolbg plscol0 plgcol0
- * plscmap1 plscmap1f1 plscolor
- *
- * Revision 1.27 1994/01/25 06:23:26 mjl
- * Moved default setting of digits variables to the correct location.
- *
- * Revision 1.26 1994/01/18 06:01:38 mjl
- * Now set default number of digits in numeric labels for axis to be switched
- * to scientific notation. Before this capability had to be enabled by the
- * user. The number of digits defaults to x:4, y:4, z:3 (xy or xyz plots).
- *
- * Revision 1.25 1994/01/17 21:36:51 mjl
- * Added function c_plgcol0 for retrieving RGB color values from cmap0
- * entries. User-contributed (I lost track of who sent it).
- */
-
- /* plcore.c
-
- Central dispatch facility for plplot.
- Also contains the plplot main data structures, external access
- routines, and initialization calls.
-
- This stuff used to be in "dispatch.h", "dispatch.c", and "base.c".
- */
-
- #include "plcore.h"
-
- /*----------------------------------------------------------------------*\
- * Driver Interface
- *
- * These routines are the low-level interface to the driver -- all calls
- * to driver functions must pass through here. For implementing driver-
- * specific functions, the escape function is provided. The command
- * stream gets duplicated to the plot buffer here.
- *
- * All functions that result in graphics actually being plotted (rather
- * than just a change of state) are filtered as necessary before being
- * passed on. The default settings do not require any filtering, i.e.
- * plplot physical coordinates are the same as the device physical
- * coordinates (currently this can't be changed anyway), and a global view
- * equal to the entire page is used.
- *
- * The reason one wants to put view-specific filtering here is that if
- * enabled, the plot buffer should receive the unfiltered data stream.
- * This allows a specific view to be used from an interactive device
- * (e.g. TCL/TK driver) but be restored to the full view at any time
- * merely by reprocessing the contents of the plot buffer.
- *
- * The metafile, on the other hand, *should* be affected by changes in the
- * view, since this is a crucial editing capability. It is recommended
- * that the initial metafile be created without a restricted global view,
- * and modification of the view done on a per-plot basis as desired during
- * subsequent processing.
- *
- \*----------------------------------------------------------------------*/
-
- enum {AT_BOP, DRAWING, AT_EOP};
-
- /* Initialize device. */
- /* The plot buffer must be called last */
-
- void
- plP_init(void)
- {
- plsc->status = AT_EOP;
-
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_init) (plsc);
-
- if (plsc->plbuf_write)
- plbuf_init(plsc);
- }
-
- /* End of page */
- /* The plot buffer must be called first */
- /* Ignore instruction if there's nothing drawn */
-
- void
- plP_eop(void)
- {
- if (plsc->status != DRAWING)
- return;
-
-
- plsc->status = AT_EOP;
-
- if (plsc->plbuf_write)
- plbuf_eop(plsc);
-
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_eop) (plsc);
-
- plClrCWindows();
- }
-
- /* Set up new page. */
- /* The plot buffer must be called last */
- /* Ignore if the bop was already issued. */
- /* It's not actually necessary to be AT_EOP here, so don't check for it. */
-
- void
- plP_bop(void)
- {
- if (plsc->status == AT_BOP)
- return;
-
- plsc->status = AT_BOP;
-
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_bop) (plsc);
-
- if (plsc->plbuf_write)
- plbuf_bop(plsc);
- }
-
- /* Tidy up device (flush buffers, close file, etc.) */
-
- void
- plP_tidy(void)
- {
- if (plsc->tidy) {
- (*plsc->tidy) (plsc->tidy_data);
- plsc->tidy = NULL;
- plsc->tidy_data = NULL;
- }
-
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_tidy) (plsc);
-
- if (plsc->plbuf_write)
- plbuf_tidy(plsc);
-
- plsc->OutFile = NULL;
- free_mem(plsc->FileName);
- }
-
- /* Change state. */
-
- void
- plP_state(PLINT op)
- {
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_state) (plsc, op);
-
- if (plsc->plbuf_write)
- plbuf_state(plsc, op);
- }
-
- /* Escape function, for driver-specific commands. */
-
- void
- plP_esc(PLINT op, void *ptr)
- {
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_esc) (plsc, op, ptr);
-
- if (plsc->plbuf_write)
- plbuf_esc(plsc, op, ptr);
- }
-
- /*----------------------------------------------------------------------*\
- * Drawing commands.
- \*----------------------------------------------------------------------*/
-
- /* Draw line between two points */
- /* The plot buffer must be called first so it gets the unfiltered data */
-
- void
- plP_line(short *x, short *y)
- {
- PLINT i, npts = 2, clpxmi, clpxma, clpymi, clpyma;
-
- plsc->status = DRAWING;
-
- if (plsc->plbuf_write)
- plbuf_line(plsc, x[0], y[0], x[1], y[1]);
-
- if (plsc->difilt) {
- for (i = 0; i < npts; i++) {
- xscl[i] = x[i];
- yscl[i] = y[i];
- }
- difilt(xscl, yscl, npts, &clpxmi, &clpxma, &clpymi, &clpyma);
- plP_pllclp(xscl, yscl, npts, clpxmi, clpxma, clpymi, clpyma, grline);
- }
- else {
- grline(x, y, npts);
- }
- }
-
- /* Draw polyline */
- /* The plot buffer must be called first */
-
- void
- plP_polyline(short *x, short *y, PLINT npts)
- {
- PLINT i, clpxmi, clpxma, clpymi, clpyma;
-
- plsc->status = DRAWING;
-
- if (plsc->plbuf_write)
- plbuf_polyline(plsc, x, y, npts);
-
- if (plsc->difilt) {
- for (i = 0; i < npts; i++) {
- xscl[i] = x[i];
- yscl[i] = y[i];
- }
- difilt(xscl, yscl, npts, &clpxmi, &clpxma, &clpymi, &clpyma);
- plP_pllclp(xscl, yscl, npts, clpxmi, clpxma, clpymi, clpyma,
- grpolyline);
- }
- else {
- grpolyline(x, y, npts);
- }
- }
-
- /* Fill polygon */
- /* The plot buffer must be called first */
-
- void
- plP_fill(short *x, short *y, PLINT npts)
- {
- PLINT i, clpxmi, clpxma, clpymi, clpyma;
-
- plsc->status = DRAWING;
-
- if (plsc->plbuf_write) {
- plsc->dev_npts = npts;
- plsc->dev_x = x;
- plsc->dev_y = y;
- plbuf_esc(plsc, PLESC_FILL, NULL);
- }
-
- if (plsc->difilt) {
- for (i = 0; i < npts; i++) {
- xscl[i] = x[i];
- yscl[i] = y[i];
- }
- difilt(xscl, yscl, npts, &clpxmi, &clpxma, &clpymi, &clpyma);
- plP_plfclp(xscl, yscl, npts, clpxmi, clpxma, clpymi, clpyma,
- grfill);
- }
- else {
- grfill(x, y, npts);
- }
- }
-
- static void
- grline(short *x, short *y, PLINT npts)
- {
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_line) (plsc, x[0], y[0], x[1], y[1]);
- }
-
- static void
- grpolyline(short *x, short *y, PLINT npts)
- {
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_polyline) (plsc, x, y, npts);
- }
-
- /* Here if the desired area fill capability isn't present, we mock up */
- /* something in software */
-
- static int foo;
-
- static void
- grfill(short *x, short *y, PLINT npts)
- {
- if (plsc->patt == 0 && ! plsc->dev_fill0) {
- if ( ! foo) {
- plwarn("Driver does not support hardware solid fills, switching to software fill.\n");
- foo = 1;
- }
- plsc->patt = 8;
- plpsty(plsc->patt);
- }
- if (plsc->patt < 0 && ! plsc->dev_fill1) {
- if ( ! foo) {
- plwarn("Driver does not support hardware pattern fills, switching to software fill.\n");
- foo = 1;
- }
- plsc->patt = ABS(plsc->patt) % 8 + 1;
- plpsty(plsc->patt);
- }
-
- if (plsc->patt <= 0) {
- plsc->dev_npts = npts;
- plsc->dev_x = x;
- plsc->dev_y = y;
-
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_esc) (plsc, PLESC_FILL, NULL);
- }
- else
- plfill_soft(x, y, npts);
- }
-
- /*----------------------------------------------------------------------*\
- * void difilt
- *
- * Driver interface filter -- passes all coordinates through a variety
- * of filters. These include filters to change :
- *
- * - mapping of meta to physical coordinates
- * - plot orientation
- * - window into plot (zooms)
- * - window into device (i.e set margins)
- *
- * The filters are applied in the order specified above. Because the
- * orientation change comes first, subsequent window specifications affect
- * the new coordinates (i.e. after a 90 degree flip, what was x is now y).
- * This is the only way that makes sense from a graphical interface
- * (e.g. TCL/TK driver).
- *
- * Where appropriate, the page clip limits are modified.
- \*----------------------------------------------------------------------*/
-
- static void
- difilt(PLINT *xscl, PLINT *yscl, PLINT npts,
- PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma)
- {
- PLINT i, x, y;
-
- /* Map meta coordinates to physical coordinates */
-
- if (plsc->difilt & PLDI_MAP) {
- for (i = 0; i < npts; i++) {
- xscl[i] = plsc->dimxax * xscl[i] + plsc->dimxb;
- yscl[i] = plsc->dimyay * yscl[i] + plsc->dimyb;
- }
- }
-
- /* Change orientation */
-
- if (plsc->difilt & PLDI_ORI) {
- for (i = 0; i < npts; i++) {
- x = plsc->dioxax * xscl[i] + plsc->dioxay * yscl[i] + plsc->dioxb;
- y = plsc->dioyax * xscl[i] + plsc->dioyay * yscl[i] + plsc->dioyb;
- xscl[i] = x;
- yscl[i] = y;
- }
- }
-
- /* Change window into plot space */
-
- if (plsc->difilt & PLDI_PLT) {
- for (i = 0; i < npts; i++) {
- xscl[i] = plsc->dipxax * xscl[i] + plsc->dipxb;
- yscl[i] = plsc->dipyay * yscl[i] + plsc->dipyb;
- }
- }
-
- /* Change window into device space and set clip limits */
- /* (this is the only filter that modifies them) */
-
- if (plsc->difilt & PLDI_DEV) {
- for (i = 0; i < npts; i++) {
- xscl[i] = plsc->didxax * xscl[i] + plsc->didxb;
- yscl[i] = plsc->didyay * yscl[i] + plsc->didyb;
- }
- *clpxmi = plsc->diclpxmi;
- *clpxma = plsc->diclpxma;
- *clpymi = plsc->diclpymi;
- *clpyma = plsc->diclpyma;
- }
- else {
- *clpxmi = plsc->phyxmi;
- *clpxma = plsc->phyxma;
- *clpymi = plsc->phyymi;
- *clpyma = plsc->phyyma;
- }
- }
-
- /*----------------------------------------------------------------------*\
- * void pldi_ini
- *
- * Updates driver interface, making sure everything is in order.
- * Even if filter is not being used, the defaults need to be set up.
- \*----------------------------------------------------------------------*/
-
- static void
- setdef_diplt()
- {
- plsc->dipxmin = 0.0;
- plsc->dipxmax = 1.0;
- plsc->dipymin = 0.0;
- plsc->dipymax = 1.0;
- }
-
- static void
- setdef_didev()
- {
- plsc->mar = 0.0;
- plsc->aspect = 0.0;
- plsc->jx = 0.0;
- plsc->jy = 0.0;
- }
-
- static void
- setdef_diori()
- {
- plsc->diorot = 0.;
- }
-
- static void
- pldi_ini(void)
- {
- if (plsc->level >= 1) {
- if (plsc->difilt & PLDI_MAP) /* Coordinate mapping */
- calc_dimap();
-
- if (plsc->difilt & PLDI_ORI) /* Orientation */
- calc_diori();
- else
- setdef_diori();
-
- if (plsc->difilt & PLDI_PLT) /* Plot window */
- calc_diplt();
- else
- setdef_diplt();
-
- if (plsc->difilt & PLDI_DEV) /* Device window */
- calc_didev();
- else
- setdef_didev();
- }
- }
-
- /*----------------------------------------------------------------------*\
- * void pldid2pc
- *
- * Converts input values from relative device coordinates to relative plot
- * coordinates. This function must be called when selecting a plot window
- * from a display driver, since the coordinates chosen by the user are
- * necessarily device-specific.
- \*----------------------------------------------------------------------*/
-
- void
- pldid2pc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
- {
- PLFLT pxmin, pymin, pxmax, pymax;
- PLFLT sxmin, symin, sxmax, symax;
- PLFLT rxmin, rymin, rxmax, rymax;
-
- #ifdef DEBUG
- fprintf(stderr, "Relative device coordinates (input): %f, %f, %f, %f\n",
- *xmin, *ymin, *xmax, *ymax);
- #endif
-
- if (plsc->difilt & PLDI_DEV) {
-
- pxmin = plsc->phyxmi + (plsc->phyxma - plsc->phyxmi) * *xmin;
- pymin = plsc->phyymi + (plsc->phyyma - plsc->phyymi) * *ymin;
- pxmax = plsc->phyxmi + (plsc->phyxma - plsc->phyxmi) * *xmax;
- pymax = plsc->phyymi + (plsc->phyyma - plsc->phyymi) * *ymax;
-
- sxmin = (pxmin - plsc->didxb) / plsc->didxax;
- symin = (pymin - plsc->didyb) / plsc->didyay;
- sxmax = (pxmax - plsc->didxb) / plsc->didxax;
- symax = (pymax - plsc->didyb) / plsc->didyay;
-
- rxmin = (sxmin - plsc->phyxmi) / (plsc->phyxma - plsc->phyxmi);
- rymin = (symin - plsc->phyymi) / (plsc->phyyma - plsc->phyymi);
- rxmax = (sxmax - plsc->phyxmi) / (plsc->phyxma - plsc->phyxmi);
- rymax = (symax - plsc->phyymi) / (plsc->phyyma - plsc->phyymi);
-
- *xmin = (rxmin < 0) ? 0 : rxmin;
- *xmax = (rxmax > 1) ? 1 : rxmax;
- *ymin = (rymin < 0) ? 0 : rymin;
- *ymax = (rymax > 1) ? 1 : rymax;
- }
-
- #ifdef DEBUG
- fprintf(stderr, "Relative plot coordinates (output): %f, %f, %f, %f\n",
- rxmin, rymin, rxmax, rymax);
- #endif
- }
-
- /*----------------------------------------------------------------------*\
- * void pldip2dc
- *
- * Converts input values from relative plot coordinates to relative
- * device coordinates.
- \*----------------------------------------------------------------------*/
-
- void
- pldip2dc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
- {
- PLFLT pxmin, pymin, pxmax, pymax;
- PLFLT sxmin, symin, sxmax, symax;
- PLFLT rxmin, rymin, rxmax, rymax;
-
- #ifdef DEBUG
- fprintf(stderr, "Relative plot coordinates (input): %f, %f, %f, %f\n",
- *xmin, *ymin, *xmax, *ymax);
- #endif
-
- if (plsc->difilt & PLDI_DEV) {
-
- pxmin = plsc->phyxmi + (plsc->phyxma - plsc->phyxmi) * *xmin;
- pymin = plsc->phyymi + (plsc->phyyma - plsc->phyymi) * *ymin;
- pxmax = plsc->phyxmi + (plsc->phyxma - plsc->phyxmi) * *xmax;
- pymax = plsc->phyymi + (plsc->phyyma - plsc->phyymi) * *ymax;
-
- sxmin = pxmin * plsc->didxax + plsc->didxb;
- symin = pymin * plsc->didyay + plsc->didyb;
- sxmax = pxmax * plsc->didxax + plsc->didxb;
- symax = pymax * plsc->didyay + plsc->didyb;
-
- rxmin = (sxmin - plsc->phyxmi) / (plsc->phyxma - plsc->phyxmi);
- rymin = (symin - plsc->phyymi) / (plsc->phyyma - plsc->phyymi);
- rxmax = (sxmax - plsc->phyxmi) / (plsc->phyxma - plsc->phyxmi);
- rymax = (symax - plsc->phyymi) / (plsc->phyyma - plsc->phyymi);
-
- *xmin = (rxmin < 0) ? 0 : rxmin;
- *xmax = (rxmax > 1) ? 1 : rxmax;
- *ymin = (rymin < 0) ? 0 : rymin;
- *ymax = (rymax > 1) ? 1 : rymax;
- }
-
- #ifdef DEBUG
- fprintf(stderr, "Relative device coordinates (output): %f, %f, %f, %f\n",
- rxmin, rymin, rxmax, rymax);
- #endif
- }
-
- /*----------------------------------------------------------------------*\
- * void plsdiplt
- *
- * Set window into plot space
- \*----------------------------------------------------------------------*/
-
- void
- c_plsdiplt(PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax)
- {
- plsc->dipxmin = (xmin < xmax) ? xmin : xmax;
- plsc->dipxmax = (xmin < xmax) ? xmax : xmin;
- plsc->dipymin = (ymin < ymax) ? ymin : ymax;
- plsc->dipymax = (ymin < ymax) ? ymax : ymin;
-
- if (xmin == 0. && xmax == 1. && ymin == 0. && ymax == 1.) {
- plsc->difilt &= ~PLDI_PLT;
- return;
- }
-
- plsc->difilt |= PLDI_PLT;
- pldi_ini();
- }
-
- /*----------------------------------------------------------------------*\
- * void plsdiplz
- *
- * Set window into plot space incrementally (zoom)
- \*----------------------------------------------------------------------*/
-
- void
- c_plsdiplz(PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax)
- {
- if (plsc->difilt & PLDI_PLT) {
- xmin = plsc->dipxmin + (plsc->dipxmax - plsc->dipxmin) * xmin;
- ymin = plsc->dipymin + (plsc->dipymax - plsc->dipymin) * ymin;
- xmax = plsc->dipxmin + (plsc->dipxmax - plsc->dipxmin) * xmax;
- ymax = plsc->dipymin + (plsc->dipymax - plsc->dipymin) * ymax;
- }
-
- plsdiplt(xmin, ymin, xmax, ymax);
- }
-
- /*----------------------------------------------------------------------*\
- * void calc_diplt
- *
- * Calculate transformation coefficients to set window into plot space.
- *
- * Note: if driver has requested to handle these commands itself, we must
- * send the appropriate escape command. If the driver succeeds it will
- * cancel the filter operation. The command is deferred until this point
- * to ensure that the driver has been initialized.
- \*----------------------------------------------------------------------*/
-
- static void
- calc_diplt(void)
- {
- PLINT pxmin, pxmax, pymin, pymax, pxlen, pylen;
-
- if (plsc->dev_di) {
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_esc) (plsc, PLESC_DI, NULL);
- }
-
- if ( ! (plsc->difilt & PLDI_PLT))
- return;
-
- pxmin = plsc->dipxmin * (plsc->phyxma - plsc->phyxmi) + plsc->phyxmi;
- pxmax = plsc->dipxmax * (plsc->phyxma - plsc->phyxmi) + plsc->phyxmi;
- pymin = plsc->dipymin * (plsc->phyyma - plsc->phyymi) + plsc->phyymi;
- pymax = plsc->dipymax * (plsc->phyyma - plsc->phyymi) + plsc->phyymi;
-
- pxlen = pxmax - pxmin;
- pylen = pymax - pymin;
- pxlen = MAX(1, pxlen);
- pylen = MAX(1, pylen);
-
- plsc->dipxax = (float) (plsc->phyxma - plsc->phyxmi) / (float) pxlen;
- plsc->dipyay = (float) (plsc->phyyma - plsc->phyymi) / (float) pylen;
- plsc->dipxb = plsc->phyxmi - plsc->dipxax * pxmin;
- plsc->dipyb = plsc->phyymi - plsc->dipyay * pymin;
- }
-
- /*----------------------------------------------------------------------*\
- * void plgdiplt
- *
- * Retrieve current window into plot space
- \*----------------------------------------------------------------------*/
-
- void
- c_plgdiplt(PLFLT *p_xmin, PLFLT *p_ymin, PLFLT *p_xmax, PLFLT *p_ymax)
- {
- *p_xmin = plsc->dipxmin;
- *p_xmax = plsc->dipxmax;
- *p_ymin = plsc->dipymin;
- *p_ymax = plsc->dipymax;
- }
-
- /*----------------------------------------------------------------------*\
- * void plsdidev
- *
- * Set window into device space using margin, aspect ratio, and
- * justification. If you want to just use the previous value for any of
- * these, just pass in the magic value PL_NOTSET.
- *
- * It is unlikely that one should ever need to change the aspect ratio
- * but it's in there for completeness.
- \*----------------------------------------------------------------------*/
-
- void
- c_plsdidev(PLFLT mar, PLFLT aspect, PLFLT jx, PLFLT jy)
- {
- plsetvar(plsc->mar, mar);
- plsetvar(plsc->aspect, aspect);
- plsetvar(plsc->jx, jx);
- plsetvar(plsc->jy, jy);
-
- if (mar == 0. && aspect == 0. && jx == 0. && jy == 0. &&
- ! (plsc->difilt & PLDI_ORI)) {
- plsc->difilt &= ~PLDI_DEV;
- return;
- }
-
- plsc->difilt |= PLDI_DEV;
- pldi_ini();
- }
-
- /*----------------------------------------------------------------------*\
- * void calc_didev
- *
- * Calculate transformation coefficients to set window into device space.
- * Calculates relative window bounds and calls plsdidxy to finish the job.
- \*----------------------------------------------------------------------*/
-
- static void
- calc_didev(void)
- {
- PLFLT lx, ly, aspect, aspdev;
- PLFLT xmin, xmax, xlen, ymin, ymax, ylen;
- PLINT pxmin, pxmax, pymin, pymax, pxlen, pylen;
-
- if (plsc->dev_di) {
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_esc) (plsc, PLESC_DI, NULL);
- }
-
- if ( ! (plsc->difilt & PLDI_DEV))
- return;
-
- /* Calculate aspect ratio of physical device */
-
- lx = (plsc->phyxma - plsc->phyxmi + 1) / plsc->xpmm;
- ly = (plsc->phyyma - plsc->phyymi + 1) / plsc->ypmm;
- aspdev = lx / ly;
-
- if (plsc->difilt & PLDI_ORI)
- aspect = plsc->aspori;
- else
- aspect = plsc->aspect;
-
- if (aspect <= 0.)
- aspect = plsc->aspdev;
-
- /* Failsafe */
-
- plsc->mar = (plsc->mar > 0.5) ? 0.5 : plsc->mar;
- plsc->mar = (plsc->mar < 0.0) ? 0.0 : plsc->mar;
- plsc->jx = (plsc->jx > 0.5) ? 0.5 : plsc->jx;
- plsc->jx = (plsc->jx < -0.5) ? -0.5 : plsc->jx;
- plsc->jy = (plsc->jy > 0.5) ? 0.5 : plsc->jy;
- plsc->jy = (plsc->jy < -0.5) ? -0.5 : plsc->jy;
-
- /* Relative device coordinates that neutralize aspect ratio difference */
-
- xlen = (aspect < aspdev) ? (aspect / aspdev) : 1.0;
- ylen = (aspect < aspdev) ? 1.0 : (aspdev / aspect);
-
- xlen *= (1.0 - 2.*plsc->mar);
- ylen *= (1.0 - 2.*plsc->mar);
-
- xmin = (1. - xlen) * (0.5 + plsc->jx);
- xmax = xmin + xlen;
-
- ymin = (1. - ylen) * (0.5 + plsc->jy);
- ymax = ymin + ylen;
-
- /* Calculate transformation coefficients */
-
- pxmin = xmin * (plsc->phyxma - plsc->phyxmi) + plsc->phyxmi;
- pxmax = xmax * (plsc->phyxma - plsc->phyxmi) + plsc->phyxmi;
- pymin = ymin * (plsc->phyyma - plsc->phyymi) + plsc->phyymi;
- pymax = ymax * (plsc->phyyma - plsc->phyymi) + plsc->phyymi;
-
- pxlen = pxmax - pxmin;
- pylen = pymax - pymin;
- pxlen = MAX(1, pxlen);
- pylen = MAX(1, pylen);
-
- plsc->didxax = (float) pxlen / (float) (plsc->phyxma - plsc->phyxmi);
- plsc->didyay = (float) pylen / (float) (plsc->phyyma - plsc->phyymi);
- plsc->didxb = pxmin - plsc->didxax * plsc->phyxmi;
- plsc->didyb = pymin - plsc->didyay * plsc->phyymi;
-
- /* Set clip limits to conform to new page size */
-
- plsc->diclpxmi = plsc->didxax * plsc->phyxmi + plsc->didxb;
- plsc->diclpxma = plsc->didxax * plsc->phyxma + plsc->didxb;
- plsc->diclpymi = plsc->didyay * plsc->phyymi + plsc->didyb;
- plsc->diclpyma = plsc->didyay * plsc->phyyma + plsc->didyb;
- }
-
- /*----------------------------------------------------------------------*\
- * void plgdidev
- *
- * Retrieve current window into device space
- \*----------------------------------------------------------------------*/
-
- void
- c_plgdidev(PLFLT *p_mar, PLFLT *p_aspect, PLFLT *p_jx, PLFLT *p_jy)
- {
- *p_mar = plsc->mar;
- *p_aspect = plsc->aspect;
- *p_jx = plsc->jx;
- *p_jy = plsc->jy;
- }
-
- /*----------------------------------------------------------------------*\
- * void plsdiori
- *
- * Set plot orientation, specifying rotation in units of pi/2.
- \*----------------------------------------------------------------------*/
-
- void
- c_plsdiori(PLFLT rot)
- {
- plsc->diorot = rot;
- if (rot == 0.) {
- plsc->difilt &= ~PLDI_ORI;
- pldi_ini();
- return;
- }
-
- plsc->difilt |= PLDI_ORI;
- pldi_ini();
- }
-
- /*----------------------------------------------------------------------*\
- * void calc_diori
- *
- * Calculate transformation coefficients to arbitrarily orient plot.
- * Preserve aspect ratios so the output doesn't suck.
- \*----------------------------------------------------------------------*/
-
- static void
- calc_diori(void)
- {
- PLFLT r11, r21, r12, r22, cost, sint;
- PLFLT x0, y0, lx, ly, aspect;
-
- if (plsc->dev_di) {
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_esc) (plsc, PLESC_DI, NULL);
- }
-
- if ( ! (plsc->difilt & PLDI_ORI))
- return;
-
- /* Center point of rotation */
-
- x0 = (plsc->phyxma + plsc->phyxmi) / 2.;
- y0 = (plsc->phyyma + plsc->phyymi) / 2.;
-
- /* Rotation matrix */
-
- r11 = cos(plsc->diorot * PI / 2.);
- r21 = sin(plsc->diorot * PI / 2.);
- r12 = -r21;
- r22 = r11;
-
- cost = ABS(r11);
- sint = ABS(r21);
-
- /* Flip aspect ratio as necessary. Grungy but I don't see a better way */
-
- aspect = plsc->aspect;
- if (aspect == 0.)
- aspect = plsc->aspdev;
-
- plsc->aspori = (aspect * cost + sint) / (aspect * sint + cost);
-
- if ( ! (plsc->difilt & PLDI_DEV)) {
- plsc->difilt |= PLDI_DEV;
- setdef_didev();
- }
- calc_didev();
-
- /* Compute scale factors */
-
- lx = plsc->phyxma - plsc->phyxmi;
- ly = plsc->phyyma - plsc->phyymi;
-
- /* Transformation coefficients */
-
- plsc->dioxax = r11;
- plsc->dioxay = r21 * (lx / ly);
- plsc->dioxb = (1. - r11) * x0 - r21 * y0 * (lx / ly);
-
- plsc->dioyax = r12 * (ly / lx);
- plsc->dioyay = r22;
- plsc->dioyb = (1. - r22) * y0 - r12 * x0 * (ly / lx);
- }
-
- /*----------------------------------------------------------------------*\
- * void plgdiori
- *
- * Get plot orientation
- \*----------------------------------------------------------------------*/
-
- void
- c_plgdiori(PLFLT *p_rot)
- {
- *p_rot = plsc->diorot;
- }
-
- /*----------------------------------------------------------------------*\
- * void plsdimap
- *
- * Set up transformation from metafile coordinates.
- * The size of the plot is scaled so as to preserve aspect ratio.
- * This isn't intended to be a general-purpose facility just yet
- * (not sure why the user would need it, for one).
- \*----------------------------------------------------------------------*/
-
- void
- c_plsdimap(PLINT dimxmin, PLINT dimxmax, PLINT dimymin, PLINT dimymax,
- PLFLT dimxpmm, PLFLT dimypmm)
- {
- plsetvar(plsc->dimxmin, dimxmin);
- plsetvar(plsc->dimxmax, dimxmax);
- plsetvar(plsc->dimymin, dimymin);
- plsetvar(plsc->dimymax, dimymax);
- plsetvar(plsc->dimxpmm, dimxpmm);
- plsetvar(plsc->dimypmm, dimypmm);
-
- plsc->difilt |= PLDI_MAP;
- pldi_ini();
- }
-
- /*----------------------------------------------------------------------*\
- * void calc_dimap
- *
- * Set up transformation from metafile coordinates. The size of the plot
- * is scaled so as to preserve aspect ratio. This isn't intended to be a
- * general-purpose facility just yet (not sure why the user would need it,
- * for one).
- \*----------------------------------------------------------------------*/
-
- static void
- calc_dimap()
- {
- PLFLT lx, ly;
- PLINT pxmin, pxmax, pymin, pymax;
- PLFLT dimxlen, dimylen, pxlen, pylen;
-
- if ((plsc->dimxmin == plsc->phyxmi) && (plsc->dimxmax == plsc->phyxma) &&
- (plsc->dimymin == plsc->phyymi) && (plsc->dimymax == plsc->phyyma) &&
- (plsc->dimxpmm == plsc->xpmm) && (plsc->dimypmm == plsc->ypmm)) {
- plsc->difilt &= ~PLDI_MAP;
- return;
- }
-
- /* Set default aspect ratio */
-
- lx = (plsc->dimxmax - plsc->dimxmin + 1) / plsc->dimxpmm;
- ly = (plsc->dimymax - plsc->dimymin + 1) / plsc->dimypmm;
-
- plsc->aspdev = lx / ly;
-
- /* Build transformation to correct physical coordinates */
-
- dimxlen = plsc->dimxmax - plsc->dimxmin;
- dimylen = plsc->dimymax - plsc->dimymin;
-
- pxmin = plsc->phyxmi;
- pxmax = plsc->phyxma;
- pymin = plsc->phyymi;
- pymax = plsc->phyyma;
- pxlen = pxmax - pxmin;
- pylen = pymax - pymin;
-
- plsc->dimxax = pxlen / dimxlen;
- plsc->dimyay = pylen / dimylen;
- plsc->dimxb = pxmin - pxlen * plsc->dimxmin / dimxlen;
- plsc->dimyb = pymin - pylen * plsc->dimymin / dimylen;
- }
-
- /*----------------------------------------------------------------------*\
- * void plflush()
- *
- * Flushes the output stream. Use sparingly, if at all.
- \*----------------------------------------------------------------------*/
-
- void
- c_plflush(void)
- {
- if (plsc->dev_flush) {
- offset = plsc->device - 1;
- (*dispatch_table[offset].pl_esc) (plsc, PLESC_FLUSH, NULL);
- }
- else {
- if (plsc->OutFile != NULL)
- fflush(plsc->OutFile);
- }
- }
-
- /*----------------------------------------------------------------------*\
- * Startup routines.
- \*----------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------*\
- * void plstar(nx, ny)
- *
- * Initialize plplot, passing in the windows/page settings.
- \*----------------------------------------------------------------------*/
-
- void
- c_plstar(PLINT nx, PLINT ny)
- {
- if (plsc->level != 0)
- plend1();
-
- plssub(nx, ny);
-
- c_plinit();
- }
-
- /*----------------------------------------------------------------------*\
- * void plstart(devname, nx, ny)
- *
- * Initialize plplot, passing the device name and windows/page settings.
- \*----------------------------------------------------------------------*/
-
- void
- c_plstart(const char *devname, PLINT nx, PLINT ny)
- {
- if (plsc->level != 0)
- plend1();
-
- plssub(nx, ny);
- plsdev(devname);
-
- c_plinit();
- }
-
- /*----------------------------------------------------------------------*\
- * void plinit()
- *
- * Initializes plplot, using preset or default options.
- \*----------------------------------------------------------------------*/
-
- void
- c_plinit(void)
- {
- PLFLT lx, ly;
- PLINT mk = 0, sp = 0, inc = 0, del = 2000;
-
- if (plsc->level != 0)
- plend1();
-
- /* Set device number */
-
- plGetDev();
-
- /* Stream number */
-
- plsc->ipls = ipls;
-
- /* Initialize color maps */
-
- plCmap0_init();
- plCmap1_init();
-
- /* Load fonts */
-
- font = 1;
- if (fontset) {
- plfntld(initfont);
- fontset = 0;
- }
- else
- plfntld(0);
-
- /* Initialize device & first page */
-
- plP_init();
- plsc->level = 1;
-
- plP_bop();
-
- /* Set up subpages */
-
- plP_subpInit();
-
- /* Set up number of allowed digits before switching to scientific notation */
- /* The user can always change this */
-
- if (plsc->xdigmax == 0)
- plsc->xdigmax = 4;
-
- if (plsc->ydigmax == 0)
- plsc->ydigmax = 4;
-
- if (plsc->zdigmax == 0)
- plsc->zdigmax = 3;
-
- /* Switch to graphics mode and set color */
-
- plgra();
- plcol(1);
-
- plstyl(0, &mk, &sp);
- plpat(1, &inc, &del);
-
- /* Set clip limits. */
-
- plsc->clpxmi = plsc->phyxmi;
- plsc->clpxma = plsc->phyxma;
- plsc->clpymi = plsc->phyymi;
- plsc->clpyma = plsc->phyyma;
-
- /* Page aspect ratio. */
-
- lx = (plsc->phyxma - plsc->phyxmi) / plsc->xpmm;
- ly = (plsc->phyyma - plsc->phyymi) / plsc->ypmm;
- plsc->aspdev = lx / ly;
-
- /* Initialize driver interface */
-
- pldi_ini();
- }
-
- /*----------------------------------------------------------------------*\
- * void plend()
- *
- * End a plotting session for all open streams.
- \*----------------------------------------------------------------------*/
-
- void
- c_plend(void)
- {
- PLINT i;
-
- for (i = PL_NSTREAMS-1; i >= 0; i--) {
- if (pls[i] != NULL) {
- plsstrm(i);
- c_plend1();
- }
- }
- plfontrel();
- }
-
- /*----------------------------------------------------------------------*\
- * void plend1()
- *
- * End a plotting session for the current stream only. After the stream
- * is ended the memory associated with the stream's PLStream data
- * structure is freed (for stream > 0), and the stream counter is set to 0
- * (the default).
- \*----------------------------------------------------------------------*/
-
- void
- c_plend1(void)
- {
- if (plsc->level > 0) {
- plsc->level = 0;
- plP_eop();
- plP_tidy();
- }
- #ifdef __riscos
- plsc->famadv = 0;
- plsc->page = 0;
- plsc->member = 0;
- #endif
-
- /* Free all malloc'ed stream memory */
-
- free_mem(plsc->plwindow);
- free_mem(plsc->geometry);
- free_mem(plsc->dev);
- free_mem(plsc->BaseName);
-
- /* Free malloc'ed stream if not in initial stream */
-
- if (ipls > 0) {
- free_mem(plsc);
- pls[ipls] = NULL;
- plsstrm(0);
- }
- }
-
- /*----------------------------------------------------------------------*\
- * void plsstrm
- *
- * Set stream number. If the data structure for a new stream is
- * unallocated, we allocate it here.
- \*----------------------------------------------------------------------*/
-
- void
- c_plsstrm(PLINT strm)
- {
- if (strm < 0 || strm >= PL_NSTREAMS) {
- fprintf(stderr,
- "plsstrm: Illegal stream number %d, must be in [0, %d]\n",
- (int) strm, PL_NSTREAMS);
- }
- else {
- ipls = strm;
- if (pls[ipls] == NULL) {
- pls[ipls] = (PLStream *) malloc((size_t) sizeof(PLStream));
- if (pls[ipls] == NULL)
- plexit("plsstrm: Out of memory.");
-
- memset((char *) pls[ipls], 0, sizeof(PLStream));
- }
- plsc = pls[ipls];
- }
- }
-
- /*----------------------------------------------------------------------*\
- * void plgstrm
- *
- * Get current stream number.
- \*----------------------------------------------------------------------*/
-
- void
- c_plgstrm(PLINT *p_strm)
- {
- *p_strm = ipls;
- }
-
- /*----------------------------------------------------------------------*\
- * void plmkstrm
- *
- * Creates a new stream and makes it the default. Differs from using
- * plsstrm(), in that a free stream number is found, and returned.
- *
- * Unfortunately, I /have/ to start at stream 1 and work upward, since
- * stream 0 is preallocated. One of the BIG flaws in the PLplot API is
- * that no initial, library-opening call is required. So stream 0 must be
- * preallocated, and there is no simple way of determining whether it is
- * already in use or not.
- \*----------------------------------------------------------------------*/
-
- void
- c_plmkstrm(PLINT *p_strm)
- {
- int i;
-
- for (i = 1; i < PL_NSTREAMS; i++) {
- if (pls[i] == NULL)
- break;
- }
-
- if (i == PL_NSTREAMS) {
- fprintf(stderr, "plmkstrm: Cannot create new stream\n");
- *p_strm = -1;
- }
- else {
- *p_strm = i;
- plsstrm(i);
- }
- }
-
- /*----------------------------------------------------------------------*\
- * void plcpstrm
- *
- * Copies state parameters from the reference stream to the current stream.
- * Tell driver interface to map device coordinates unless flags == 1.
- *
- * This function is used for making save files of selected plots (e.g.
- * from the TK driver). After initializing, you can get a copy of the
- * current plot to the specified device by switching to this stream and
- * issuing a plcpstrm() and a plreplot(), with calls to plbop() and
- * pleop() as appropriate. The plot buffer must have previously been
- * enabled (done automatically by some display drivers, such as X).
- \*----------------------------------------------------------------------*/
-
- static void
- cp_color(PLColor *to, PLColor *from)
- {
- to->r = from->r;
- to->g = from->g;
- to->b = from->b;
- }
-
- void
- c_plcpstrm(PLINT iplsr, PLINT flags)
- {
- int i;
- PLStream *plsr;
-
- plsr = pls[iplsr];
- if (plsr == NULL) {
- fprintf(stderr, "plcpstrm: stream %d not in use\n", (int) iplsr);
- return;
- }
-
- /* Plot buffer -- need to copy file pointer so that plreplot() works */
- /* This also prevents inadvertent writes into the plot buffer */
-
- plsc->plbufFile = plsr->plbufFile;
-
- /* Driver interface */
- /* Transformation must be recalculated in current driver coordinates */
-
- if (plsr->difilt & PLDI_PLT)
- plsdiplt(plsr->dipxmin, plsr->dipymin, plsr->dipxmax, plsr->dipymax);
-
- if (plsr->difilt & PLDI_DEV)
- plsdidev(plsr->mar, plsr->aspect, plsr->jx, plsr->jy);
-
- if (plsr->difilt & PLDI_ORI)
- plsdiori(plsr->diorot);
-
- /* Map device coordinates */
-
- if ( ! (flags & 0x01))
- plsdimap(plsr->phyxmi, plsr->phyxma, plsr->phyymi, plsr->phyyma,
- plsr->xpmm, plsr->ypmm);
-
- /* Palettes */
-
- plsc->icol0 = plsr->icol0;
- plsc->ncol0 = plsr->ncol0;
- plsc->icol1 = plsr->icol1;
- plsc->ncol1 = plsr->ncol1;
-
- cp_color(&plsc->curcolor, &plsr->curcolor);
- for (i = 0; i < 16; i++) {
- plsc->cmap0setcol[i] = plsr->cmap0setcol[i];
- cp_color(&plsc->cmap0[i], &plsr->cmap0[i]);
- }
-
- plsc->cmap1set = plsr->cmap1set;
- for (i = 0; i < 256; i++) {
- cp_color(&plsc->cmap1[i], &plsr->cmap1[i]);
- }
-
- /* Initialize if it hasn't been done yet. */
-
- if (plsc->level == 0)
- plinit();
- }
-
- /*----------------------------------------------------------------------*\
- * void plGetDev()
- *
- * If the the user has not already specified the output device, or the
- * one specified is either: (a) not available, (b) "?", or (c) NULL, the
- * user is prompted for it.
- *
- * Prompting quits after 10 unsuccessful tries in case the user has
- * run the program in the background with insufficient input.
- \*----------------------------------------------------------------------*/
-
- static void
- plGetDev()
- {
- PLINT dev, i, count, length;
- char response[80];
-
- /* Device name already specified. See if it is valid. */
-
- if (*(plsc->DevName) != '\0' && *(plsc->DevName) != '?') {
- length = strlen(plsc->DevName);
- for (i = 0; i < npldrivers; i++) {
- if ((*plsc->DevName == *dispatch_table[i].pl_DevName) &&
- (strncmp(plsc->DevName,
- dispatch_table[i].pl_DevName, length) == 0))
- break;
- }
- if (i < npldrivers) {
- plsc->device = i + 1;
- return;
- }
- else {
- printf("Requested device %s not available\n", plsc->DevName);
- }
- }
-
- dev = 0;
- count = 0;
-
- if (npldrivers == 1)
- dev = 1;
-
- /* User hasn't specified it correctly yet, so we prompt */
-
- while (dev < 1 || dev > npldrivers) {
- printf("\nPlotting Options:\n");
- for (i = 0; i < npldrivers; i++) {
- printf(" <%2d> %-10s %s\n", i + 1, dispatch_table[i].pl_DevName,
- dispatch_table[i].pl_MenuStr);
- }
- if (ipls == 0)
- printf("\nEnter device number or keyword: ");
- else
- printf("\nEnter device number or keyword (stream %d): ",
- (int) ipls);
-
- fgets(response, sizeof(response), stdin);
-
- /* First check to see if device keyword was entered. */
- /* Final "\n" in response messes things up, so ignore it. */
-
- length = strlen(response);
- if (*(response - 1 + length) == '\n')
- length--;
-
- for (i = 0; i < npldrivers; i++) {
- if (!strncmp(response, dispatch_table[i].pl_DevName,
- (unsigned int) length))
- break;
- }
- if (i < npldrivers) {
- dev = i + 1;
- }
- else {
- if ((dev = atoi(response)) < 1) {
- printf("Invalid device.");
- dev = 0;
- }
- }
- if (count++ > 10)
- plexit("plGetDev: Too many tries.");
- }
- plsc->device = dev;
- strcpy(plsc->DevName, dispatch_table[dev - 1].pl_DevName);
- }
-
- /*----------------------------------------------------------------------*\
- * void c_plfont(ifont)
- *
- * Sets the global font flag to 'ifont'.
- \*----------------------------------------------------------------------*/
-
- void
- c_plfont(PLINT ifont)
- {
- if (plsc->level < 1) {
- plabort("plfont: Please call plinit first");
- return;
- }
- if (ifont < 1 || ifont > 4) {
- plabort("plfont: Invalid font");
- return;
- }
-
- font = ifont;
- }
-
- /*----------------------------------------------------------------------*\
- * void plfontld()
- *
- * Load specified font set.
- \*----------------------------------------------------------------------*/
-
- void
- c_plfontld(PLINT fnt)
- {
- if (fnt != 0)
- fnt = 1;
-
- if (plsc->level > 0)
- plfntld(fnt);
- else {
- initfont = fnt;
- fontset = 1;
- }
- }
-
- /*----------------------------------------------------------------------*\
- * void plreplot()
- *
- * Replays contents of plot buffer to current device/file.
- \*----------------------------------------------------------------------*/
-
- void
- c_plreplot(void)
- {
- if (plsc->plbufFile != NULL) {
- plRemakePlot(plsc);
- }
- else {
- plwarn("plreplot: plot buffer not available");
- }
- }
-
- /*----------------------------------------------------------------------*\
- * void plgFileDevs()
- *
- * Returns a list of file-oriented device names and their menu strings,
- * for use in a graphical interface. The caller must allocate enough
- * space for (*p_menustr) and (*p_devname) to hold a pointer for each
- * device -- 20 or so is plenty. E.g. char *menustr[20].
- \*----------------------------------------------------------------------*/
-
- void
- plgFileDevs(char ***p_menustr, char ***p_devname, int *p_ndev)
- {
- int i, j;
-
- for (i = j = 0; i < npldrivers; i++) {
- if (dispatch_table[i].pl_type == 0) {
- (*p_menustr)[j] = dispatch_table[i].pl_MenuStr;
- (*p_devname)[j] = dispatch_table[i].pl_DevName;
- j++;
- }
- }
- (*p_menustr)[j] = NULL;
- (*p_devname)[j] = NULL;
- *p_ndev = j;
- }
-
- /*----------------------------------------------------------------------*\
- * Various external access routines.
- \*----------------------------------------------------------------------*/
-
- /* Get output device parameters. */
-
- void
- c_plgpage(PLFLT *p_xp, PLFLT *p_yp,
- PLINT *p_xleng, PLINT *p_yleng, PLINT *p_xoff, PLINT *p_yoff)
- {
- *p_xp = plsc->xdpi;
- *p_yp = plsc->ydpi;
- *p_xleng = plsc->xlength;
- *p_yleng = plsc->ylength;
- *p_xoff = plsc->xoffset;
- *p_yoff = plsc->yoffset;
- }
-
- /* Set output device parameters. Usually ignored by the driver. */
-
- void
- c_plspage(PLFLT xp, PLFLT yp, PLINT xleng, PLINT yleng, PLINT xoff, PLINT yoff)
- {
- if (xp)
- plsc->xdpi = xp;
- if (yp)
- plsc->ydpi = yp;
-
- if (xleng)
- plsc->xlength = xleng;
- if (yleng)
- plsc->ylength = yleng;
-
- if (xoff)
- plsc->xoffset = xoff;
- if (yoff)
- plsc->yoffset = yoff;
-
- plsc->pageset = 1;
- }
-
- /* Set the number of subwindows in x and y */
-
- void
- c_plssub(PLINT nx, PLINT ny)
- {
- if (nx > 0)
- plsc->nsubx = nx;
- if (ny > 0)
- plsc->nsuby = ny;
-
- if (plsc->level > 0)
- plP_subpInit();
- }
-
- /* Set the device (keyword) name */
-
- void
- c_plsdev(const char *devname)
- {
- if (plsc->level > 0) {
- plwarn("plsdev: Must be called before plinit.");
- return;
- }
- if (devname != NULL) {
- strncpy(plsc->DevName, devname, sizeof(plsc->DevName) - 1);
- plsc->DevName[sizeof(plsc->DevName) - 1] = '\0';
- }
- }
-
- /* Get the current stream pointer */
-
- void
- plgpls(PLStream **p_pls)
- {
- *p_pls = plsc;
- }
-
- /* Set the function pointer for the keyboard event handler */
-
- void
- plsKeyEH(void (*KeyEH) (PLKey *, void *, int *), void *KeyEH_data)
- {
- plsc->KeyEH = KeyEH;
- plsc->KeyEH_data = KeyEH_data;
- }
-
- /* Set the function pointer for the mouse event handler */
-
- void
- plsMouseEH(void (*MouseEH) (PLMouse *, void *, int *), void *MouseEH_data)
- {
- plsc->MouseEH = MouseEH;
- plsc->MouseEH_data = MouseEH_data;
- }
-
- /* Set orientation. Must be done before calling plinit. */
-
- void
- c_plsori(PLINT ori)
- {
- plsdiori((PLFLT) ori);
- }
-
- /*
- * Set pen width. Can be done any time, but before calling plinit is best
- * since otherwise it may be volatile (i.e. reset on next page advance).
- * If width <= 0 or is unchanged by the call, nothing is done.
- */
-
- void
- c_plwid(PLINT width)
- {
- if (width != plsc->width && width > 0) {
- plsc->width = width;
-
- if (plsc->level > 0) {
- if ( ! plsc->widthlock)
- plP_state(PLSTATE_WIDTH);
- }
- }
- }
-
- /* Obsolete. Use page driver interface instead. */
-
- void
- c_plsasp(PLFLT asp)
- {
- }
-
- /* I've canned this for now */
-
- void
- c_plslpb(PLFLT lpbxmi, PLFLT lpbxma, PLFLT lpbymi, PLFLT lpbyma)
- {
- }
-
- /* Set the output file pointer */
-
- void
- plgfile(FILE **p_file)
- {
- *p_file = plsc->OutFile;
- }
-
- /* Get the output file pointer */
-
- void
- plsfile(FILE *file)
- {
- plsc->OutFile = file;
- }
-
- /* Get the (current) output file name. Must be preallocated to >80 bytes */
- /* Beyond that, I truncate it. You have been warned. */
-
- void
- c_plgfnam(char *fnam)
- {
- strncpy(fnam, plsc->FileName, 79);
- fnam[79] = '\0';
- }
-
- /* Set the output file name. */
-
- void
- c_plsfnam(const char *fnam)
- {
- plP_sfnam(plsc, fnam);
- }
-
- /* Set the pause (on end-of-page) status */
-
- void
- c_plspause(PLINT pause)
- {
- plsc->nopause = ! pause;
- }
-
- /* Set the floating point precision (in number of places) in numeric labels. */
-
- void
- c_plprec(PLINT setp, PLINT prec)
- {
- plsc->setpre = setp;
- plsc->precis = prec;
- }
-
- /* Get the floating point precision (in number of places) in numeric labels. */
-
- void
- plP_gprec(PLINT *p_setp, PLINT *p_prec)
- {
- *p_setp = plsc->setpre;
- *p_prec = plsc->precis;
- }
-
- /*
- * Set the escape character for text strings.
- * From C you can pass as a character, from Fortran it needs to be the decimal
- * ASCII value. Only selected characters are allowed to prevent the user from
- * shooting himself in the foot (a '\' isn't allowed since it conflicts with
- * C's use of backslash as a character escape).
- */
-
- void
- c_plsesc(char esc)
- {
- switch (esc) {
- case '!': /* ASCII 33 */
- case '#': /* ASCII 35 */
- case '$': /* ASCII 36 */
- case '%': /* ASCII 37 */
- case '&': /* ASCII 38 */
- case '*': /* ASCII 42 */
- case '@': /* ASCII 64 */
- case '^': /* ASCII 94 */
- case '~': /* ASCII 126 */
- plsc->esc = esc;
- break;
-
- default:
- plwarn("plsesc: Invalid escape character, ignoring.");
- }
- }
-
- /* Get the escape character for text strings. */
-
- void
- plgesc(char *p_esc)
- {
- if (plsc->esc == '\0')
- plsc->esc = '#';
-
- *p_esc = plsc->esc;
- }
-
- /* Get the current library version number */
- /* Note: you MUST have allocated space for this (80 characters is safe) */
-
- void
- c_plgver(char *p_ver)
- {
- strcpy(p_ver, PLPLOT_VERSION);
- }
-
- /* Set inferior X window */
-
- void
- plsxwin(PLINT window_id)
- {
- plsc->window_id = window_id;
- }
-
- /*----------------------------------------------------------------------*\
- * These set/get information for family files, and may be called prior
- * to plinit to set up the necessary parameters. Arguments:
- *
- * fam familying flag (boolean)
- * num member number
- * bmax maximum member size
- \*----------------------------------------------------------------------*/
-
- /* Get family file parameters */
-
- void
- c_plgfam(PLINT *p_fam, PLINT *p_num, PLINT *p_bmax)
- {
- *p_fam = plsc->family;
- *p_num = plsc->member;
- *p_bmax = plsc->bytemax;
- }
-
- /* Set family file parameters */
-
- void
- c_plsfam(PLINT fam, PLINT num, PLINT bmax)
- {
- if (plsc->level > 0)
- plwarn("plsfam: Must be called before plinit.");
-
- if (fam >= 0)
- plsc->family = fam;
- if (num >= 0)
- plsc->member = num;
- if (bmax >= 0)
- plsc->bytemax = bmax;
- }
-
- /* Advance to the next family file on the next new page */
-
- void
- c_plfamadv(void)
- {
- plsc->famadv = 1;
- }
-
- /*----------------------------------------------------------------------*\
- * Interface routines for axis labling parameters.
- * See pldtik.c for more info.
- \*----------------------------------------------------------------------*/
-
- /* Get x axis labeling parameters */
-
- void
- c_plgxax(PLINT *p_digmax, PLINT *p_digits)
- {
- *p_digmax = plsc->xdigmax;
- *p_digits = plsc->xdigits;
- }
-
- /* Set x axis labeling parameters */
-
- void
- c_plsxax(PLINT digmax, PLINT digits)
- {
- plsc->xdigmax = digmax;
- plsc->xdigits = digits;
- }
-
- /* Get y axis labeling parameters */
-
- void
- c_plgyax(PLINT *p_digmax, PLINT *p_digits)
- {
- *p_digmax = plsc->ydigmax;
- *p_digits = plsc->ydigits;
- }
-
- /* Set y axis labeling parameters */
-
- void
- c_plsyax(PLINT digmax, PLINT digits)
- {
- plsc->ydigmax = digmax;
- plsc->ydigits = digits;
- }
-
- /* Get z axis labeling parameters */
-
- void
- c_plgzax(PLINT *p_digmax, PLINT *p_digits)
- {
- *p_digmax = plsc->zdigmax;
- *p_digits = plsc->zdigits;
- }
-
- /* Set z axis labeling parameters */
-
- void
- c_plszax(PLINT digmax, PLINT digits)
- {
- plsc->zdigmax = digmax;
- plsc->zdigits = digits;
- }
-
- /* Get character default height and current (scaled) height */
-
- void
- c_plgchr(PLFLT *p_def, PLFLT *p_ht)
- {
- *p_def = plsc->chrdef;
- *p_ht = plsc->chrht;
- }
-
- /*----------------------------------------------------------------------*\
- * These should not be called by the user.
- \*----------------------------------------------------------------------*/
-
- /* Get x-y domain in world coordinates for 3d plots */
-
- void
- plP_gdom(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
- {
- *p_xmin = plsc->domxmi;
- *p_xmax = plsc->domxma;
- *p_ymin = plsc->domymi;
- *p_ymax = plsc->domyma;
- }
-
- /* Get vertical (z) scale parameters for 3-d plot */
-
- void
- plP_grange(PLFLT *p_zscl, PLFLT *p_zmin, PLFLT *p_zmax)
- {
- *p_zscl = plsc->zzscl;
- *p_zmin = plsc->ranmi;
- *p_zmax = plsc->ranma;
- }
-
- /* Get parameters used in 3d plots */
-
- void
- plP_gw3wc(PLFLT *p_dxx, PLFLT *p_dxy, PLFLT *p_dyx, PLFLT *p_dyy, PLFLT *p_dyz)
- {
- *p_dxx = plsc->cxx;
- *p_dxy = plsc->cxy;
- *p_dyx = plsc->cyx;
- *p_dyy = plsc->cyy;
- *p_dyz = plsc->cyz;
- }
-
- /* Get viewport boundaries in physical coordinates */
-
- void
- plP_gvpp(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
- {
- *p_ixmin = plsc->vppxmi;
- *p_ixmax = plsc->vppxma;
- *p_iymin = plsc->vppymi;
- *p_iymax = plsc->vppyma;
- }
-
- /* Set viewport boundaries in physical coordinates */
-
- void
- plP_svpp(PLINT ixmin, PLINT ixmax, PLINT iymin, PLINT iymax)
- {
- plsc->vppxmi = ixmin;
- plsc->vppxma = ixmax;
- plsc->vppymi = iymin;
- plsc->vppyma = iymax;
- }
-
- /* Get subpage boundaries in physical coordinates */
-
- void
- plP_gspp(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
- {
- *p_ixmin = plsc->sppxmi;
- *p_ixmax = plsc->sppxma;
- *p_iymin = plsc->sppymi;
- *p_iymax = plsc->sppyma;
- }
-
- /* Get clip boundaries in physical coordinates */
-
- void
- plP_gclp(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
- {
- *p_ixmin = plsc->clpxmi;
- *p_ixmax = plsc->clpxma;
- *p_iymin = plsc->clpymi;
- *p_iymax = plsc->clpyma;
- }
-
- /* Set clip boundaries in physical coordinates */
-
- void
- plP_sclp(PLINT ixmin, PLINT ixmax, PLINT iymin, PLINT iymax)
- {
- plsc->clpxmi = ixmin;
- plsc->clpxma = ixmax;
- plsc->clpymi = iymin;
- plsc->clpyma = iymax;
- }
-
- /* Get physical device limits in physical coordinates */
-
- void
- plP_gphy(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
- {
- *p_ixmin = plsc->phyxmi;
- *p_ixmax = plsc->phyxma;
- *p_iymin = plsc->phyymi;
- *p_iymax = plsc->phyyma;
- }
-
- /* Set physical device limits in physical coordinates */
-
- void
- plP_sphy(PLINT ixmin, PLINT ixmax, PLINT iymin, PLINT iymax)
- {
- plsc->phyxmi = ixmin;
- plsc->phyxma = ixmax;
- plsc->phyymi = iymin;
- plsc->phyyma = iymax;
- }
-
- /* Get number of subpages on physical device and current subpage */
-
- void
- plP_gsub(PLINT *p_nx, PLINT *p_ny, PLINT *p_cs)
- {
- *p_nx = plsc->nsubx;
- *p_ny = plsc->nsuby;
- *p_cs = plsc->cursub;
- }
-
- /* Set number of subpages on physical device and current subpage */
-
- void
- plP_ssub(PLINT nx, PLINT ny, PLINT cs)
- {
- plsc->nsubx = nx;
- plsc->nsuby = ny;
- plsc->cursub = cs;
- }
-
- /* Get font and color attributes */
-
- void
- plP_gatt(PLINT *p_ifnt, PLINT *p_icol0)
- {
- *p_ifnt = font;
- *p_icol0 = plsc->icol0;
- }
-
- /* Set font and color attributes */
-
- void
- plP_satt(PLINT ifnt, PLINT icol0)
- {
- font = ifnt;
- plsc->icol0 = icol0;
- }
-
- /* Get subpage boundaries in normalized device coordinates */
-
- void
- plP_gspd(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
- {
- *p_xmin = plsc->spdxmi;
- *p_xmax = plsc->spdxma;
- *p_ymin = plsc->spdymi;
- *p_ymax = plsc->spdyma;
- }
-
- /* Get viewport boundaries in normalized device coordinates */
-
- void
- plP_gvpd(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
- {
- *p_xmin = plsc->vpdxmi;
- *p_xmax = plsc->vpdxma;
- *p_ymin = plsc->vpdymi;
- *p_ymax = plsc->vpdyma;
- }
-
- /* Get viewport boundaries in normalized device coordinates */
-
- void
- plP_svpd(PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax)
- {
- plsc->vpdxmi = xmin;
- plsc->vpdxma = xmax;
- plsc->vpdymi = ymin;
- plsc->vpdyma = ymax;
- }
-
- /* Get viewport boundaries in world coordinates */
-
- void
- plP_gvpw(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
- {
- *p_xmin = plsc->vpwxmi;
- *p_xmax = plsc->vpwxma;
- *p_ymin = plsc->vpwymi;
- *p_ymax = plsc->vpwyma;
- }
-
- /* Set viewport boundaries in world coordinates */
-
- void
- plP_svpw(PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax)
- {
- plsc->vpwxmi = xmin;
- plsc->vpwxma = xmax;
- plsc->vpwymi = ymin;
- plsc->vpwyma = ymax;
- }
-
- /* Get number of pixels to a millimeter */
-
- void
- plP_gpixmm(PLFLT *p_x, PLFLT *p_y)
- {
- *p_x = plsc->xpmm;
- *p_y = plsc->ypmm;
- }
-
- /* Set number of pixels to a millimeter */
-
- void
- plP_spixmm(PLFLT x, PLFLT y)
- {
- plsc->xpmm = x;
- plsc->ypmm = y;
- plsc->umx = 1000.0 / plsc->xpmm;
- plsc->umy = 1000.0 / plsc->ypmm;
- }
-
- /* All the drivers call this to set physical pixels/mm. */
-
- void
- plP_setpxl(PLFLT xpmm0, PLFLT ypmm0)
- {
- plsc->xpmm = xpmm0;
- plsc->ypmm = ypmm0;
- plsc->umx = 1000.0 / plsc->xpmm;
- plsc->umy = 1000.0 / plsc->ypmm;
- }
-
- /* Sets up physical limits of plotting device and the mapping between
- normalized device coordinates and physical coordinates. */
-
- void
- plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
- {
- PLFLT mpxscl, mpyscl;
-
- plP_sphy(xmin, xmax, ymin, ymax);
-
- plsc->dpxscl = xmax - xmin;
- plsc->dpxoff = xmin;
- plsc->dpyscl = ymax - ymin;
- plsc->dpyoff = ymin;
-
- mpxscl = plsc->xpmm;
- if (xmax <= xmin)
- mpxscl = -plsc->xpmm;
- mpyscl = plsc->ypmm;
- if (ymax <= ymin)
- mpyscl = -plsc->ypmm;
- plP_smp(mpxscl, (PLFLT) (xmin), mpyscl, (PLFLT) (ymin));
- }
-
- /* Get transformation variables for world coordinates to mm */
-
- void
- plP_gwm(PLFLT *p_xscl, PLFLT *p_xoff, PLFLT *p_yscl, PLFLT *p_yoff)
- {
- *p_xscl = plsc->wmxscl;
- *p_xoff = plsc->wmxoff;
- *p_yscl = plsc->wmyscl;
- *p_yoff = plsc->wmyoff;
- }
-
- /* Set transformation variables for world coordinates to mm */
-
- void
- plP_swm(PLFLT xscl, PLFLT xoff, PLFLT yscl, PLFLT yoff)
- {
- plsc->wmxscl = xscl;
- plsc->wmxoff = xoff;
- plsc->wmyscl = yscl;
- plsc->wmyoff = yoff;
- }
-
- /* Get transformation variables for millimeters from bottom left */
-
- void
- plP_gmp(PLFLT *p_xscl, PLFLT *p_xoff, PLFLT *p_yscl, PLFLT *p_yoff)
- {
- *p_xscl = plsc->mpxscl;
- *p_xoff = plsc->mpxoff;
- *p_yscl = plsc->mpyscl;
- *p_yoff = plsc->mpyoff;
- }
-
- /* Set transformation variables for millimeters from bottom left */
-
- void
- plP_smp(PLFLT xscl, PLFLT xoff, PLFLT yscl, PLFLT yoff)
- {
- plsc->mpxscl = xscl;
- plsc->mpxoff = xoff;
- plsc->mpyscl = yscl;
- plsc->mpyoff = yoff;
- }
-